package com.zkingsoft.web.htmlCompiltJsp;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.collections.CollectionUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.matrix.core.tools.DateUtil;
import com.matrix.core.tools.StringUtils;
import com.matrix.core.tools.UUIDUtil;
import com.zkingsoft.web.bean.WebAd;
import com.zkingsoft.web.bean.WebAdcolumn;
import com.zkingsoft.web.bean.WebNav;

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

public class Main {

	private static final String COMPANY_ID = Config.PARAM.getString("companyId");

	private static String jspHead = "<%@ page language=\"java\" import=\"java.util.*\" pageEncoding=\"utf-8\"%>\r\n"
			+ "<%@ taglib uri=\"http://java.sun.com/jstl/core_rt\" prefix=\"c\"%>\r\n"
			+ "<%@ taglib uri=\"http://java.sun.com/jsp/jstl/fmt\" prefix=\"fmt\"%>\r\n"
			+ "<%@ taglib prefix=\"fn\" uri=\"http://java.sun.com/jsp/jstl/functions\"%>\r\n"
			+ "<c:set var=\"path\" value=\"${pageContext.request.contextPath }\" />\r\n"
			+ "<%@ taglib tagdir=\"/WEB-INF/tags\" prefix=\"matrix\"%>\r\n"
			+ "<%@ taglib uri=\"http://matrixcsm.zkingsoft.com\" prefix=\"cms\"%>\r\n";

	// 记录所有要查询的广告查询标签
	private static StringBuffer adTags;

	// 解析出来的广告位
	private static List<WebAd> webAdList;
	// 解析导航栏
	private static List<WebNav> webNavList;
	
	// 记录导航栏的jsp路径和html路径对应关系
	private static Map<String, String> NavUrlMap = new HashMap<>();

	/**
	 * 1、在系统中新增company
	 * 2、修改配置文件databasse.properties 与 config.json
	 * 3、解析前分离出 _top.html，_footer.html 用 navElement 标记导航栏 top 标记头部 footer标记底部, 
	 * 4、navWarp 标记导航栏的包裹框一般是ul，暂时不能自动转换含二级导航的导航,解析完成后导航栏中会多一个li 注意删除
	 * 5、注意样式中的 > 会被转换成 &gt; 需要手动替换 或者避免使用 
	 * 2、把静态文件全部放在nginx中
	 * 6、修改导航栏为jsp的取值，注意在后台要能被编辑需要加class="zy"
	 */
	// TODO 加上资讯的处理，新闻按照一定的格式也可以导入到jsp中
	// TODO 产品以及产品的分类需要加上点击编辑的功能
	public static void main(String[] args) throws IOException, SQLException {
//		 cleanData();
		compiltHtml();
//		 insertDB();

	}

	private static void compiltHtml() throws IOException, SQLException {
		// 输入html 输出jsp
		List<File> htmlFiles = getHtmlFiles();

		for (File file : htmlFiles) {
			// 记录所有要查询的广告查询标签
			adTags = new StringBuffer();
			// 解析出来的广告栏
			webAdList = new ArrayList<>();
			// 导航栏只处理一次
			webNavList = new ArrayList<>();

			System.out.println("开始处理页面" + file.getName());
			Document document = Jsoup.parse(file, "UTF-8");
			// 导航栏只处理一次
			if (file.getName().equals("_top.html")) {
				analysiseTopEelement(document);
			} else if (!file.getName().equals("_footer.html")) {

				// 除了footer页面和top页面其他界面需要删除公共部分
				Elements top = document.getElementsByClass("header");
				if (CollectionUtils.isNotEmpty(top)) {
					top.before("<jsp:include page='_top.jsp'></jsp:include>");
					top.remove();
				}

				Elements footer = document.getElementsByClass("footer-wrap");
				if (CollectionUtils.isNotEmpty(footer)) {
					footer.before("<jsp:include page='_footer.jsp'></jsp:include>");
					footer.remove();
				}

			} else {
				// 底部页面加上js配置
				document.append("<script type='text/javascript' > ${自定义js} </script>");
			}

			List<Element> nodes = document.children();
			System.out.println("解析页面元素。。");
			printElement(nodes);
			
			String jspFile = Config.PARAM.getString("jspDir") + file.getName().replaceAll(".html", "") + ".jsp";
			System.out.println("输出jsp页面" + jspFile);
			File jsp = new File(jspFile);
			if (jsp.exists()) {
				System.out.println(jsp.getName() + "文件已经存在，程序跳过。。。");
				continue;
			} else {
				FileWriter fw = new FileWriter(jsp);
				String cmsTag = "<cms:ads   code=\"" + adTags.toString().subSequence(0, adTags.length() - 1)
						+ "\"  ></cms:ads>\r\n";
				String jspBody = jspHead + cmsTag;
				if (file.getName().equals("_top.html")) {

					Elements top = document.getElementsByClass("header");

					if (top.size() == 1) {
						jspBody = jspBody + top.get(0).toString();
					} else {
						System.out.println("top文件中找到" + top.size() + "个top样式，必须保证该样式的唯一");
						return;
					}

				} else if (file.getName().equals("_footer.html")) {

					Elements footer = document.getElementsByClass("footer-wrap");
					if (footer.size() == 1) {
						jspBody = jspBody + footer.get(0).toString();
					} else {
						System.out.println("footer文件中找到" + footer.size() + "个footer样式，必须保证该样式的唯一");
						return;
					}

				} else {
					jspBody = jspBody + document.html();
				}
				//处理标签大小写问题
				jspBody=jspBody.replaceAll("foreach", "forEach").replaceAll("HTTP", "'http'");
				fw.write(jspBody);
				fw.close();
				insertDB();
			}

		}

	}

	/**
	 * 处理头部和尾部
	 * 
	 * @author JIANGYOUYAO
	 * @email 935090232@qq.com
	 * @date 2018年11月17日
	 * @param document
	 * @throws IOException
	 */
	private static void analysiseTopEelement(Document document) throws IOException {

		Elements top = document.getElementsByClass("header");
		//查询包裹导航的元素
		Elements navWarp = document.getElementsByClass("navWarp");
		if (top.size() == 1) {
			// 解析top中的导航nav
			Elements navs = top.get(0).getElementsByClass("navElement");
			for (int i = 0; i < navs.size(); i++) {
				if (navs.get(i).hasText()) {
					WebNav webNav = new WebNav();
					webNav.setCompanyId(COMPANY_ID);
					webNav.setNavName(navs.get(i).text());
					webNav.setNavOrderby(navs.size() - i);
					webNav.setNavType(Config.PARAM.getString("navType"));
					webNav.setNavShow(WebNav.SHOW);
					webNav.setParentId(0L);
					webNav.setNavUrl(
							Config.PARAM.getString("navUrl") + navs.get(i).attr("href").replaceAll(".html", ""));
					NavUrlMap.put(navs.get(i).attr("href"), webNav.getNavUrl());
					webNavList.add(webNav);
				}
			}
			//把导航处理成<c:foreach>
			Element nav=navs.get(0);
			//固定导航的格式为ul>li>a
			String li="<li>"
			+"<c:if test='${fn:contains(item.navUrl, HTTP)}'> <a href='${item.navUrl }' data-type='nav'  data-id='${item.navId }' class='navElement zy'>${item.navName }</a> </c:if>"
			+"<c:if test='${!fn:contains(item.navUrl, HTTP)}'> <a href='${path }/${item.navUrl }' data-type='nav'  data-id='${item.navId }' class='navElement zy'>${item.navName }</a></c:if>"      
		    +"<li>";
			//清除导航
			navWarp.empty();
			navWarp.append("<c:forEach var='item' items='${"+Config.PARAM.getString("navType").toLowerCase()+"Nav }' >"+li+"</c:forEach>");
		}
	}

	private static List<File> getHtmlFiles() {
		List<File> htmlFiles = new ArrayList<>();
		File htmlDir = new File(Config.PARAM.getString("htmlDir"));
		File[] files = htmlDir.listFiles();
		for (File file : files) {
			if (file.getName().endsWith(".html")) {
				htmlFiles.add(file);
			}
		}
		return htmlFiles;
	}

	// 把数据插入数据库
	private static void insertDB() throws SQLException {

		Connection conn = JdbcUtil.getMysqlConnection();
		PreparedStatement ps = null;
		StringBuffer sql = new StringBuffer();
		String time = DateUtil.dateToString(new Date(), DateUtil.DATE_FORMAT_MM);
		try {
			for (WebAd webAd : webAdList) {
				String s = "INSERT INTO `web_ad` (`ad_title`,   `ad_time`,   `ad_url`, `company_id`, `code`,`ad_img`) VALUES ('"
						+ webAd.getAdTitle() + "',   '" + time + "',  '" + webAd.getAdUrl() + "', '"
						+ webAd.getCompanyId() + "', '" + webAd.getCode() + "' , '" + webAd.getAdImg() + "'  );\r\n";
				// System.out.println(s);
				ps = conn.prepareStatement(s);
				ps.execute();
			}

			for (WebNav webNav : webNavList) {
				String s = "INSERT INTO `web_nav` (`nav_name`,   `parent_id`,   `nav_url`, `nav_type`,`company_id`,`nav_orderby`,`navShow`) VALUES ('"
						+ webNav.getNavName() + "',   '" + 0 + "',  '" + webNav.getNavUrl() + "', '"
						+ webNav.getNavType() + "', '" + webNav.getCompanyId() + "', '" + webNav.getNavOrderby()
						+ "', '" + webNav.getNavShow() + "' );\r\n";
				System.out.println(s);
				ps = conn.prepareStatement(s);
				ps.execute();
			}

			System.out.println("数据插入成功！");
		} catch (SQLException e) {
			e.printStackTrace();
			conn.rollback();
			System.out.println("数据插入失败！");
		} finally {
			JdbcUtil.closeResource(ps, conn);
		}
	}

	private static void printElement(List<Element> nodes) {
		for (Element element : nodes) {
			analysisElement(element);
			if (CollectionUtils.isNotEmpty(element.children())) {
				printElement(element.children());
			}
		}

	}

	/**
	 * 清除数据库数据
	 */
	private static void cleanData() throws SQLException {

		Connection conn = JdbcUtil.getMysqlConnection();
		PreparedStatement ps = null;
		try {
			conn.prepareStatement(
					"delete from web_ad  where company_id = '" + Config.PARAM.getString("companyId") + "' ; ")
					.execute();
			conn.prepareStatement(
					"delete from web_nav where company_id = '" + Config.PARAM.getString("companyId") + "' ; ")
					.execute();
			System.out.println("清除数据成功！");
		} catch (SQLException e) {
			e.printStackTrace();
			conn.rollback();
			System.out.println("清除数据失败！");
		} finally {
			JdbcUtil.closeResource(ps, conn);
		}
	}

	/**
	 * 分析元素节点
	 */
	private static void analysisElement(Element element) {

		// 网站头部名称
		String pageTitle = "";
		if (StringUtils.isNotBlank(element.attr("style"))) {
			String style = element.attr("style");
			style = style.replaceAll("\r|\n", "");
			// 处理style行内元素的背景图片
			if (style.indexOf("images") > 0 && style.indexOf("http://") < 0) {
				style = style.replaceAll("images", Config.PARAM.getString("imagePath") + "images");
				element.attr("style", style);
			}

		}

		if (element.tagName().equals("title")) {
			pageTitle = element.text();
			// 标题处理 需要放在第一个判断
			element.text(pageTitle + "${网页标题}");
			element.before("<link rel=icon sizes=any   href='${浏览器logo}' >");

		} else if (StringUtils.isNotBlank(element.ownText()) && !element.hasClass("navElement")) {
			// 广告节点
			String code = toHanyuPinyin(element.ownText()) + "_" + webAdList.size();
			adTags.append("'" + code + "',\r\n");
			WebAd webAd = new WebAd();
			webAd.setAdTitle(element.ownText());
			webAd.setCode(code);
			webAd.setPage(pageTitle);
			webAd.setCompanyId(COMPANY_ID);
			// 如果元素节点是a标签则记录a标签
			if (element.tagName().equals("a")) {
				// 判断是否为导航栏中的链接
				if (NavUrlMap.containsKey(element.attr("href"))) {
					webAd.setAdUrl(NavUrlMap.get(element.attr("href")));
				} else {
					webAd.setAdUrl(element.attr("href"));
				}
				element.attr("href", "${" + code + ".adUrl}");
			}
			webAdList.add(webAd);
			element.text("${" + code + ".adTitle}");
			element.addClass("zy");
			element.attr("data-type", "ad");
			element.attr("data-id", "${" + code + ".adId}");

		} else if (element.tagName().equals("head")) {
			// 头部新增关键词标签
			element.append("<meta name='keywords' content='${网页关键词}'><meta name='description' content='${网页描述 }' />");

		} else if (element.tagName().equals("link") && element.attr("rel").equals("stylesheet")) {
			// 样式文件处理（注意先把样式文件放在对应的公司的resource文件夹中）
			String href = element.attr("href");
			if (!href.startsWith("http")) {
				element.attr("href", Config.PARAM.getString("resourcePath") + href);
			}
		} else if (element.tagName().equals("style")) {
			// 处理样式中的背景图片url
			String style = element.html();
			style = style.replaceAll("images/", Config.PARAM.getString("resourcePath") + "images/");
			element.html(style);

		} else if (element.tagName().equals("script") && StringUtils.isNotBlank(element.attr("src"))) {
			// 样式文件处理（注意先把样式文件放在对应的公司的resource文件夹中）
			String href = element.attr("src");
			if (!href.startsWith("http")) {
				element.attr("src", Config.PARAM.getString("imagePath") + href);
			}
		} else if (element.tagName().equals("img")) {
			String src = element.attr("src");
			if (!src.startsWith("http")) {
				src = Config.PARAM.getString("imagePath") + src;
			}
			// 图片广告节点
			String code = "img_" + getRandomVariableName(5)+webAdList.size();
			adTags.append("'" + code + "',\r\n");
			WebAd webAd = new WebAd();
			webAd.setAdImg(src);
			webAd.setCode(code);
			webAd.setCompanyId(COMPANY_ID);
			webAdList.add(webAd);
			element.attr("src", "${" + code + ".adImg}");
			element.addClass("zy");
			element.attr("data-type", "ad");
			element.attr("data-id", "${" + code + ".adId}");
		}

	}

	public static String getRandomVariableName(int length) {
		String strHead = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$";
		String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$";
		Random random = new Random();
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < length; i++) {
			if (i == 0) {
				int number = random.nextInt(strHead.length());
				sb.append(strHead.charAt(number));
			} else {
				int number = random.nextInt(str.length());
				sb.append(str.charAt(number));
			}
		}
		return sb.toString();
	}

	/**
	 * 将文字转为汉语拼音
	 * 
	 * @param chineselanguage
	 *            要转成拼音的中文
	 */
	public static String toHanyuPinyin(String ChineseLanguage) {
		if (ChineseLanguage.length() > 5) {
			ChineseLanguage = ChineseLanguage.substring(0, 6);
		}
		char[] cl_chars = ChineseLanguage.trim().toCharArray();
		String hanyupinyin = "";
		HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
		defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);// 输出拼音全部小写
		defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);// 不带声调
		defaultFormat.setVCharType(HanyuPinyinVCharType.WITH_V);
		try {
			for (int i = 0; i < cl_chars.length; i++) {
				if (String.valueOf(cl_chars[i]).matches("[\u4e00-\u9fa5]+")) {// 如果字符是中文,则将中文转为汉语拼音
					String py = PinyinHelper.toHanyuPinyinStringArray(cl_chars[i], defaultFormat)[0];
					py = firstUpcase(py);
					hanyupinyin += py;
				} else {// 如果字符不是中文,则不转换
					if (StringUtils.isNotBlank(cl_chars[i] + "") && !isSpecialChar(cl_chars[i] + "")) {
						hanyupinyin += cl_chars[i];
					}

				}
			}
		} catch (BadHanyuPinyinOutputFormatCombination e) {
			System.out.println("字符不能转成汉语拼音");
		}
		//转换为空的情况
		if(StringUtils.isBlank(hanyupinyin)){
			hanyupinyin="ZY_"+webAdList.size();
			
		}else if(isStartWithNumber(hanyupinyin) || isSpecialChar(hanyupinyin.substring(0, 1)) ){
			//转换数字或者特殊字符开头的情况
			hanyupinyin="ZY_"+hanyupinyin;
		}
		return hanyupinyin;
	}

	public static boolean isStartWithNumber(String str) {
		Pattern pattern = Pattern.compile("[0-9]*");
		Matcher isNum = pattern.matcher(str.charAt(0) + "");
		if (!isNum.matches()) {
			return false;
		}
		return true;
	}

	/**
	 * 首字母大写
	 * 
	 * @author JIANGYOUYAO
	 * @email 935090232@qq.com
	 * @date 2019年1月26日
	 * @param str
	 * @return
	 */
	private static String firstUpcase(String str) {

		StringBuffer stringbf = new StringBuffer();
		Matcher m = Pattern.compile("([a-z])([a-z]*)", Pattern.CASE_INSENSITIVE).matcher(str);
		while (m.find()) {
			m.appendReplacement(stringbf, m.group(1).toUpperCase() + m.group(2).toLowerCase());
		}
		return m.appendTail(stringbf).toString();
	}

	/**
	 * 判断是否含有特殊字符
	 *
	 * @param str
	 * @return true为包含，false为不包含
	 */
	public static boolean isSpecialChar(String str) {

		String regEx = "[ -_`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]|\n|\r|\t";
		Pattern p = Pattern.compile(regEx);
		Matcher m = p.matcher(str);
		return m.find();
	}
}
